import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
import { setupCache } from "axios-cache-adapter";

// import StorageManager, { TOKEN_KEY } from "@/services/storage";
import type { HttpRequestParams, Config } from "./types";
import CancelToken from "./cancel-token";

// Create `axios-cache-adapter` instance
const cache = setupCache({
  maxAge: 15 * 60 * 1000,
});

// 创建取消请求令牌
const cancelToken = new CancelToken();

// 请求重试
// get("/users"); // 请求失败不重试
// get("/users", { retryTimes: 2 }); // 请求失败, 重试2次
const retryAdapterEnhancer = (adapter: any, options: any) => {
  const { times = 0, delay = 300 } = options;

  return async (config: any) => {
    const { retryTimes = times, retryDelay = delay } = config;
    let __retryCount = 0;
    const request: any = async () => {
      try {
        return await adapter(config);
      } catch (err) {
        if (!retryTimes || __retryCount >= retryTimes) {
          return Promise.reject(err);
        }
        __retryCount++;
        // 延时处理
        const delay = new Promise<void>((resolve) => {
          setTimeout(() => {
            resolve();
          }, retryDelay);
        });
        // 重新发起请求
        return delay.then(() => {
          return request();
        });
      }
    };
    return request();
  };
};

const defaultConfig = {
  baseURL: process.env.VUE_APP_BASE_API,
  // 请求超时时间
  timeout: 6000,
  // 适配器, 请求重试
  // adapter: retryAdapterEnhancer(axios.defaults.adapter, {
  //   retryDelay: 1000,
  // }),
  adapter: cache.adapter,
  validateStatus: (status: number) => {
    // 成功状态码范围
    return status >= 200 && status < 500;
  },
  headers: {
    // 设置默认请求头
    "Access-Control-Allow-Origin": "*",
    Accept: "application/json, text/plain, */*",
    "Access-Control-Allow-Headers":
      "Origin, Accept, Content-Type, Authorization, Access-Control-Allow-Origin",
  },
};

// 创建一个单例
const instance: AxiosInstance = axios.create(defaultConfig);

// 默认错误处理方式
const onError = (error: AxiosResponse | any) => {
  // console.log('网络异常:', error);
  let errorMessage = error?.message ?? "未知异常";
  const response = error?.response;
  const status = error?.status ?? -1000;
  if (response) {
    switch (status) {
      case 500:
        errorMessage = "服务器内部错误(500)";
        break;
      case 501:
        errorMessage = "服务未实现(501)";
        break;
      case 502:
        errorMessage = "网络错误(502)";
        break;
      case 503:
        errorMessage = "服务不可用(503)";
        break;
      case 504:
        errorMessage = "网络超时(504)";
        break;
      case 505:
        errorMessage = "HTTP版本不受支持(505)";
        break;
      default:
        errorMessage = `服务错误类型(${
          response.status ? response.status : "未知"
        })`;
    }
  } else {
    if (errorMessage.match(/network error/gi)) {
      errorMessage = "网络似乎出了点问题";
    }
    if (errorMessage.match("timeout")) {
      errorMessage = "数据接口请求超时";
    }

    if (errorMessage.includes("Request failed with status code")) {
      errorMessage = `数据接口${errorMessage.substr(
        errorMessage.length - 3
      )} 异常`;
    }
  }

  if (error.message) {
    // console.log("错误提示框:", errorMessage);
    // @ts-ignore
    new LightTip(errorMessage, 2000, "error");
  }

  return {
    code: status,
    message: errorMessage,
  };
};

// 处理网络请求带来的校验
const checkStatus = (response: AxiosResponse) => {
  // console.info("checkStatus", "网络请求", response);

  // -1000 自己定义，连接错误的status
  const status = response?.status ?? -1000;

  // 401: 未登录
  // 未登录则跳转登录页面，并携带当前页面的路径
  // 在登录成功后返回当前页面，这一步需要在登录页操作。
  if (status === 401) {
    // StorageManager.remove(TOKEN_KEY);
    // const url = window.location.hash.substr(1);
    // if (/^\/login/.test(url)) {
    //   router.push(url);
    // } else {
    //   router.push(`/login?redirect=${escape(url)}`);
    // }
  }
  // 403 Token过期
  // 登录过期对用户进行提示
  // 清除本地token和清空vuex中token对象
  // 跳转登录页面
  if (status === 403) {
    // Message({
    //   showClose: true,
    //   message: "登录过期, 请重新登录",
    //   type: "error",
    //   duration: 3 * 1000
    // });
    // StorageManager.remove(TOKEN_KEY);
    // store.commit(`auth/${SET_LOGIN_STATUS}`, false);
    // setTimeout(() => {
    //   router.replace({
    //     path: "/login",
    //     query: {
    //       redirect: router.currentRoute.fullPath
    //     }
    //   });
    // }, 1000);
  }
  if (
    (status >= 200 && status < 300) ||
    status === 304 ||
    status === 400 ||
    status === 404
  ) {
    return response.data;
  }

  return {
    code: status,
    message: "服务异常",
  };
};

// Add a request interceptors
instance.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    cancelToken.add(config);
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// Add a response interceptors
instance.interceptors.response.use(
  (response: AxiosResponse) => {
    const config = response.config;
    cancelToken.remove(config);
    return Promise.resolve(checkStatus(response));
  },
  (error) => {
    return Promise.reject(onError(error));
  }
);

export const extendConfig = (config: Config) => {
  // const token = StorageManager.get(TOKEN_KEY);
  let headers = { ...config.headers };

  if (config && config.token) {
    const authHeaders = {
      "Content-Type": "application/json; charset=UTF-8",
      Authorization: `${config.token}`,
    };
    headers = { ...config.headers, ...authHeaders };
  } else {
    const authHeaders = {
      "Content-Type": "application/json; charset=UTF-8",
      Authorization: "",
    };
    headers = { ...config.headers, ...authHeaders };
  }

  const _config = {
    baseURL:
      config && config.server ? config.server : process.env.VUE_APP_BASE_API,
    ...config,
    headers,
  };

  return _config;
};

export default {
  // 获取 Instance
  getHttpInstance() {
    return instance;
  },
  // 获取 Interceptors
  getInterceptors() {
    return instance.interceptors;
  },
  // 获取 Uri
  getUri(config: AxiosRequestConfig) {
    return instance.getUri(config);
  },
  /**
   *
   * @param config
   */
  request(config: AxiosRequestConfig) {
    return axios.request(config).then(checkStatus).then(onError);
  },

  /**
   * head方法，对应head请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   * @param {Object} config [请求时配置的HTTP相关参数]
   */
  async head({ url, payload, config }: HttpRequestParams): Promise<any> {
    const _config = extendConfig(config);
    try {
      return await instance.head(url, { ..._config, params: payload });
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },

  /**
   * options方法，对应options请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   * @param {Object} config [请求时配置的HTTP相关参数]
   */
  async options({ url, payload, config }: HttpRequestParams): Promise<any> {
    const _config = extendConfig(config);
    try {
      return await instance.options(url, { ..._config, params: payload });
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },

  /**
   * get方法，对应get请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   * @param {Object} config [请求时配置的HTTP相关参数]
   */
  async get({ url, payload, config }: HttpRequestParams): Promise<any> {
    const _config = extendConfig(config);
    try {
      return await instance.get(url, { ..._config, params: payload });
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },

  /**
   * post方法，对应post请求
   * @param {String} url [请求的url地址]
   * @param {Object} payload [请求时携带的参数]
   * @param {Object} config [请求时配置的HTTP相关参数]
   */
  async post({ url, payload, config }: HttpRequestParams): Promise<any> {
    try {
      const _config = extendConfig(config);
      return await instance.post(url, payload, _config);
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },
  async patch({ url, payload, config }: HttpRequestParams): Promise<any> {
    try {
      const _config = extendConfig(config);
      return await instance.patch(url, payload, _config);
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },
  async put({ url, payload, config }: HttpRequestParams): Promise<any> {
    try {
      const _config = extendConfig(config);
      return await instance.put(url, payload, _config);
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },
  async delete({ url, payload, config }: HttpRequestParams): Promise<any> {
    try {
      const _config = extendConfig(config);
      _config.data = payload;
      return await instance.delete(url, _config);
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },
  async upload({
    url,
    payload,
    config,
    callback,
  }: HttpRequestParams): Promise<any> {
    try {
      const _config = extendConfig(config);
      const _headers = _config.headers;
      const _conf = {
        ..._config,
        onUploadProgress: callback,
        headers: {
          ..._headers,
          "Content-Type": "multipart/form-data",
        },
      };
      return await instance.post(url, payload, _conf);
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },
  async download({
    url,
    payload,
    config,
    callback,
  }: HttpRequestParams): Promise<any> {
    try {
      const _config = extendConfig(config);
      const _conf = {
        ..._config,
        onDownloadProgress: callback,
        responseType: "blob",
      };
      // @ts-ignore
      return await instance.post(url, payload, _conf);
    } catch (error: any) {
      throw new Error(`HttpService ${error?.message}`);
    }
  },
};
